package com.example.hzzrpcclient.config;

import com.example.hzzrpcclient.config.dto.RpcServerDto;
import com.example.hzzrpcclient.config.netty.NettyMainClient;
import com.example.hzzrpcclient.config.registercenter.RedisRegisterCenter;
import com.example.hzzrpcclient.util.GuardedObject;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author ：hzz
 * @description：TODO
 * @date ：2022/1/2 22:14
 */
@Slf4j
public class RpcClientProxy implements InvocationHandler {

    private RedisRegisterCenter redisRegisterCenter;

    private NettyMainClient nettyMainClient;

    public RpcClientProxy(RedisRegisterCenter redisRegisterCenter, NettyMainClient nettyMainClient) {
        this.redisRegisterCenter = redisRegisterCenter;
        this.nettyMainClient = nettyMainClient;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();//方法名，hello()
        String serverName = method.getDeclaringClass().getName();//接口名：MyServiceServer，用来寻找服务
        RpcServerDto rpcServerDto = redisRegisterCenter.searchRpcServer(serverName);
        Channel connect = nettyMainClient.connect(rpcServerDto.getIp(), rpcServerDto.getPort());
        long start = System.currentTimeMillis();

        String msgId = UUID.randomUUID().toString();
        connect.writeAndFlush(new String( msgId ).getBytes()).addListener(
                future -> {
                    long time = System.currentTimeMillis() - start;
                    if (!future.isSuccess()) {
                        log.error("下发失败,msgId=[{}],耗时[{}]ms", msgId, time);
                        return;
                    }
                    if (time > 20000) {
                        log.warn("指令操作=[{}],下发异常耗时,msgId=[{}],耗时[{}]ms", 20000, msgId, time);
                        return;
                    }
                    log.info("下发成功,msgId=[{}],耗时[{}]ms", msgId, time);
                });

        // 阻塞
        GuardedObject<String> go = GuardedObject.create(msgId);
        String resPayloadPacket = go.getAndThrow(res ->{
            return (res.indexOf(msgId)>-1);
        }, 5000, TimeUnit.MILLISECONDS);

        return resPayloadPacket;
    }

}
